package com.cqhfan.imservice.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqhfan.api.clients.user.UserClient;
import com.cqhfan.core.constans.DateConstants;
import com.cqhfan.core.constans.MqConstants;
import com.cqhfan.core.enums.ChatTypeEnum;
import com.cqhfan.core.enums.MessageTypeEnum;
import com.cqhfan.core.exceptions.BizException;
import com.cqhfan.core.utils.UserContext;
import com.cqhfan.imservice.mapper.ChatGroupMapper;
import com.cqhfan.imservice.service.ChatGroupService;
import com.cqhfan.imservice.service.ChatGroupUserService;
import com.cqhfan.imservice.service.ChatListService;
import com.cqhfan.imservice.service.ImMessageService;
import com.cqhfan.mq.strategy.MqMessageHelper;
import com.cqhfan.pojo.im.dto.CreateGroupDTO;
import com.cqhfan.pojo.im.dto.WebSocketMessageDTO;
import com.cqhfan.pojo.im.po.ChatGroup;
import com.cqhfan.pojo.im.po.ChatGroupUser;
import com.cqhfan.pojo.im.po.ChatList;
import com.cqhfan.pojo.im.vo.ChatGroupInfoVO;
import com.cqhfan.pojo.im.vo.GroupMemberVO;
import com.cqhfan.pojo.user.po.User;
import com.cqhfan.redis.constants.RedisConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 眭传洪
 * @create 2025-08-17 0:05
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatGroupServiceImpl extends ServiceImpl<ChatGroupMapper, ChatGroup> implements ChatGroupService {

    private final ChatGroupUserService chatGroupUserService;

    private final UserClient userClient;

    private final StringRedisTemplate stringRedisTemplate;

    private final ChatListService chatListService;

    private final MqMessageHelper mqMessageHelper;

    private final ImMessageService imMessageService;

    @Override
    @Transactional
    public Long createChatGroup(CreateGroupDTO body) {
        String groupName = body.getGroupName();
        String desc = body.getDesc();
        String groupAvatar = body.getGroupAvatar();
        List<Long> memberIds = body.getMemberIds();
        Long userId = UserContext.getUser();

        // 构建群聊信息
        ChatGroup chatGroup = new ChatGroup();
        chatGroup.setGroupAvatar(groupAvatar);
        chatGroup.setGroupName(groupName);
        chatGroup.setCreateTime(LocalDateTime.now());
        chatGroup.setGroupLeaderId(userId);
        chatGroup.setDesc(desc);
        chatGroup.setTotal(0);
        save(chatGroup);
        Long groupId = chatGroup.getId();

        // 保存群聊用户信息
        List<ChatGroupUser> chatGroupUsers = memberIds.stream().map(item -> {
            ChatGroupUser chatGroupUser = new ChatGroupUser();
            chatGroupUser.setCreateTime(LocalDateTime.now());
            chatGroupUser.setUserId(item);
            chatGroupUser.setGroupId(groupId);
            return chatGroupUser;
        }).toList();
        chatGroupUserService.saveBatch(chatGroupUsers);

        // 保存聊天列表
        List<ChatList> chatLists = chatGroupUsers.stream().map(item -> {
            ChatList chatList = new ChatList();
            chatList.setType(ChatTypeEnum.MULTI);
            chatList.setGroupId(groupId);
            chatList.setUserId(item.getUserId());
            chatList.setCreateTime(LocalDateTime.now());
            return chatList;
        }).toList();
        chatListService.saveBatch(chatLists);

        // 将群成员存到redis
        String key = RedisConstants.IM.GROUP_MEMBERS_KEY_PREFIX + groupId;
        stringRedisTemplate.opsForSet().add(key, memberIds.stream().map(String::valueOf).toList().toArray(new String[0]));

        // mq通知在线的所有用户创建群聊的消息
        WebSocketMessageDTO messageDTO = WebSocketMessageDTO.builder()
                .chatType(ChatTypeEnum.MULTI.getValue())
                .messageType(MessageTypeEnum.CREATE_GROUP.getValue())
                .groupId(groupId)
                .senderId(userId)
                .chatTime(DateUtil.format(LocalDateTime.now(), DateConstants.DATE_TIME_FORMAT))
                .build();
        mqMessageHelper.sendMessage(
                MqConstants.EXCHANGE.CHAT_CREATE_GROUP_EXCHANGE,
                null,
                messageDTO
        );
        return groupId;
    }

    @Override
    public ChatGroupInfoVO getChatGroupInfo(Long groupId) {
        // 查询群聊信息
        ChatGroup chatGroup = getById(groupId);
        if (chatGroup == null) {
            throw new BizException("群聊信息为空");
        }

        // 查询群的人员信息
        List<ChatGroupUser> groupUsers = chatGroupUserService.lambdaQuery().eq(ChatGroupUser::getGroupId, groupId).list();
        if (CollUtil.isEmpty(groupUsers)) {
            throw new BizException("群成员为空， groupId: " + groupId);
        }

        // 拿到用户信息
        List<Long> userIds = groupUsers.stream().map(ChatGroupUser::getUserId).toList();
        List<User> users = userClient.listByIds(userIds);
        if (CollUtil.isEmpty(users)) {
            throw new BizException("群聊用户信息获取失败");
        }
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, u -> u));

        // 组装vo
        ChatGroupInfoVO result = new ChatGroupInfoVO();
        result.setId(groupId);
        result.setGroupName(chatGroup.getGroupName());
        result.setGroupAvatar(chatGroup.getGroupAvatar());
        result.setTotal(chatGroup.getTotal());
        List<GroupMemberVO> members = new ArrayList<>(groupUsers.size());
        for (ChatGroupUser groupUser : groupUsers) {
            User user = userMap.get(groupUser.getUserId());
            if (user == null) {
                continue;
            }
            Long userId = groupUser.getUserId();
            GroupMemberVO vo = new GroupMemberVO();
            vo.setId(userId);

            vo.setNickName(user.getNickName());
            vo.setAvatar(user.getAvatar());
            members.add(vo);
        }
        result.setMembers(members);
        return result;
    }

    @Override
    public void noticeChatGroupCreateMsg(String message) {
        WebSocketMessageDTO messageDTO = JSONUtil.toBean(message, WebSocketMessageDTO.class);
        imMessageService.sendGroupMessage(message, messageDTO.getGroupId(), messageDTO.getSenderId());
    }

}
